//
// Created by dell on 2023/12/14.
//

#ifndef WIN_DEMO_XORENCRYPT_H
#define WIN_DEMO_XORENCRYPT_H

#include <iostream>
#include <Windows.h>
#include <string>
#include <fstream>
#include <cstdlib>


#pragma warning (disable: 4996)//禁止sprintf函数警告
#define MAX_STR_LEN 1024
typedef unsigned char CUSTOM_BYTE;


namespace CodeConvert {
    //生成随机8位二进制字节
    static CUSTOM_BYTE GetTransFlag() {
        // 设置生成种子
        srand(time(nullptr));
        //生成一个随机数，取最后一个字节
        return (rand() % 256 & 0xFF);
    }

    /**
     * 异或加密
     * @param pbDest 输出加密的密文
     * @param pbSrc 源数据
     * @return
     */
    int XorEncrypt(CUSTOM_BYTE *pbDest, const CUSTOM_BYTE *pbSrc) //加密
    {
        int nLen = strlen((char *) pbSrc);//获取数据长度（若信息中有0x00间隔，修改函数将长度作为入参）
        if (nLen <= 0) {
            return 0;
        }
        CUSTOM_BYTE TransFlag = GetTransFlag();//用于异或运算的一字节
        CUSTOM_BYTE byTempSrc[MAX_STR_LEN] = {0};
        memcpy(byTempSrc, pbSrc, nLen);
        byTempSrc[nLen] = TransFlag;//将运算字节附到信息尾部
        //进行异或加密
        for (int i = 0; i < nLen; ++i) {
            byTempSrc[i] ^= TransFlag >> (i % 8);
        }
        //将二进制转换为字符串输出
        char sztmp[4];
        for (int i = 0; i <= nLen; ++i) {
            sprintf(sztmp, "%02X", byTempSrc[i]);
            strcat((char *) pbDest, sztmp);
        }
        return (2 * nLen + 2);
    }

    /**
     * 解密
     * @param pbDest 输出解密后的数据
     * @param pbSrc 被加密的密文
     * @return
     */
    int XorDecrypt(CUSTOM_BYTE *pbDest, const CUSTOM_BYTE *pbSrc) //解密
    {
        int nLenSrc = strlen((char *) pbSrc);
        int nLenDes = nLenSrc / 2;
        if (nLenDes <= 0) {
            return 0;
        }
        //将字符串转换为字节
        CUSTOM_BYTE h1, h2;
        CUSTOM_BYTE s1, s2;
        for (int i = 0; i < nLenDes; i++) {
            h1 = pbSrc[2 * i];
            h2 = pbSrc[2 * i + 1];
            s1 = toupper(h1) - 0x30;
            if (s1 > 9)
                s1 -= 7;
            s2 = toupper(h2) - 0x30;
            if (s2 > 9)
                s2 -= 7;
            pbDest[i] = s1 * 16 + s2;
        }
        //解密为原字符
        for (int i = 0; i < nLenDes - 1; ++i) {
            pbDest[i] ^= pbDest[nLenDes - 1] >> (i % 8);
        }
        pbDest[nLenDes - 1] = 0x00;
        return nLenDes - 1;
    }
}


#endif //WIN_DEMO_XORENCRYPT_H